package main

import "fmt"

//通过接口实现OCP设计原则
//'开-闭'原则（Open-Closed Principle,常缩写为OCP）
//对扩展是开放的，对修改是关闭的
// type Pet interface {
// 	eat()
// 	sleep()
// }
// type Dog struct {
// 	name string
// 	age  int
// }

// func (dog Dog) eat() {
// 	fmt.Println("dog eat...")
// }
// func (dog Dog) sleep() {
// 	fmt.Println("dog sleep...")
// }

// type Cat struct {
// 	name string
// 	age  int
// }

// func (cat Cat) eat() {
// 	fmt.Println("cat eat...")
// }
// func (cat Cat) sleep() {
// 	fmt.Println("cat sleep...")
// }

// type Person struct {
// 	name string
// }

// //为Person添加一个养宠物方法
// func (per Person) care(pet Pet) {
// 	pet.eat()
// 	pet.sleep()
// }
// func main() {
// 	dog := Dog{}
// 	cat := Cat{}
// 	per := Person{}
// 	per.care(dog)
// 	per.care(cat)
// }

//继承 - 结构体嵌套
// type Animal struct {
// 	name string
// 	age  int
// }

// func (a Animal) eat() {
// 	fmt.Println("eat...")
// }
// func (a Animal) sleep() {
// 	fmt.Println("sleep...")
// }

// type Dog struct {
// 	Animal
// }
// type Cat struct {
// 	Animal
// }

// func main() {
// 	dog := Dog{
// 		Animal{
// 			name: "dog",
// 			age:  2},
// 	}
// 	cat := Cat{
// 		Animal{
// 			name: "cat",
// 			age:  3},
// 	}
// 	dog.eat()
// 	dog.sleep()
// 	cat.eat()
// 	cat.sleep()
// }

//模拟OOP的属性和方法
//golang没有面向对象的概念，也没有封装的概念，
//但是可以通过结构体struct和函数绑定来实现OOP的属性和方法等特性。
//接收者 receiver 方法。
// type Person struct {
// 	name string
// 	age  int
// }

// func (per Person) eat() {
// 	fmt.Println("eat...")
// }
// func (per Person) sleep() {
// 	fmt.Println("sleep...")
// }
// func (per Person) work() {
// 	fmt.Println("work...")
// }
// func main() {
// 	per := Person{
// 		name: "tom",
// 		age:  20,
// 	}
// 	fmt.Printf("per: %v\n", per) //per: {tom 20}
// 	per.eat()
// 	per.sleep()
// 	per.work()
// }

//构造函数
type Person1 struct {
	name string
	age  int
}

func NewPerson(name string, age int) (*Person1, error) {
	if name == "" {
		return nil, fmt.Errorf("name 不能为空")
	}
	if age < 0 {
		return nil, fmt.Errorf("age 不能小于0")
	}
	return &Person1{name: name, age: age}, nil
}

func main() {
	person, err := NewPerson("tom", 20)
	if err == nil {
		fmt.Printf("person: %v\n", *person)
	}
}
